/**
  ******************************************************************************
  * @file    MultiTimerA.c
  * @author  woshiashuai
  * @version V1.0
  * @date    2023-05-11
  * @brief   软件定时器-数组版
  *
  ******************************************************************************
  * @attention
  *
  * 版权声明:内容为编者原创,遵循CC4.0BY-SA版权协议,转载请附上出处链接和本声明
  * 出处链接:https://gitee.com/woshiashuai/mcu_development_module.git
  *
  ******************************************************************************
  */

/* 包含头文件-----------------------------------------------------------------*/
#include "MultiTimerA.h"
/* 私有宏定义-----------------------------------------------------------------*/
#define TIMER_A_TASK_SIZE (20u)     // 最大任务数量(1-255)
/* 私有类型定义---------------------------------------------------------------*/
typedef struct timerACtrl {
	volatile unsigned int curTicks; // 当前计数值
	unsigned int targetTicks;       // 目标计数值
	unsigned char run;              // 运行状态 0:不运行 1:运行
	void(* callback)(void);         // 回调函数
} timerA_t;
/* 私有变量-------------------------------------------------------------------*/
static timerA_t timerATasks[TIMER_A_TASK_SIZE]; // 软件定时器任务数组
/* 全局变量-------------------------------------------------------------------*/
/* 私有函数原型---------------------------------------------------------------*/

/* 软件定时器使用举例
// LED翻转函数
void ledToggleProc(void)
{
	// user write handle
	;
}
// 1ms定时器
void TIM1_IRQHandler(void)
{
	timerA_timer();
}
int main()
{
	unsigned char timerID = 0;

	timerID = timerA_create(0, 500, ledToggleProc, TIMER_A_START);
	
	while(1) {
		timerA_loop();
	}
}
*/

/**
  * @brief  创建软件定时器任务
  * @note   None
  * @param  id:定时器任务ID  0:新建任务  !0:更新此任务
  * @param  targetTicks:定时器装载值(目前计数)
  * @param  callback:定时器回调函数
  * @param  run:是否运行  0:不运行  1:运行
  * @retval 0:定时器任务已满  !0:定时器任务ID
  */
unsigned char timerA_create(unsigned char id, unsigned int targetTicks, void(* callback)(void), unsigned char run)
{
	unsigned char i = 0;
	
	if(0 == id) {
		for(i = 0; i < TIMER_A_TASK_SIZE; i++) {
			if(0 == timerATasks[i].targetTicks) {
				timerATasks[i].targetTicks = targetTicks;
				timerATasks[i].curTicks = 0;
				timerATasks[i].run	= run;
				timerATasks[i].callback = callback;
				return i + 1;
			}
		}
	} else {
		timerATasks[id - 1].targetTicks = targetTicks;
		timerATasks[id - 1].curTicks = 0;
		timerATasks[id - 1].run = run;
		timerATasks[id - 1].callback = callback;
		return id;
	}
	
	return 0;
}
/**
  * @brief  删除软件定时器任务
  * @note   None
  * @param  None
  * @retval None
  */
void timerA_delete(unsigned char id)
{
	if(id < 1 || id > TIMER_A_TASK_SIZE) return ;
	
	timerATasks[id - 1].targetTicks = 0;
	timerATasks[id - 1].curTicks = 0;
	timerATasks[id - 1].run = 0;
}

/**
  * @brief  软件定时器任务循环调度
  * @note   此函数一般放置在大循环中，回调函数在此执行
  * @param  None
  * @retval None
  */
void timerA_loop(void)
{
	static unsigned char i = 0;
	
	for(i = 0; i < TIMER_A_TASK_SIZE; i++) {
		if(timerATasks[i].curTicks >= timerATasks[i].targetTicks && timerATasks[i].run) {
			timerATasks[i].callback();
			timerATasks[i].curTicks = 0;
		}
	}
}
/**
  * @brief  软件定时器任务时基函数
  * @note   此函数加入到定时器中，此函数执行周期即是软件定时器时基周期
  * @param  None
  * @retval None
  */
void timerA_timer(void)
{
	static unsigned char i = 0;
	
	for(i = 0; i < TIMER_A_TASK_SIZE; i++) {
		if(timerATasks[i].curTicks < timerATasks[i].targetTicks && timerATasks[i].run) {
			timerATasks[i].curTicks++;
		}
	}
}

/**
  * @brief  设置指定软件定时器任务的当前计数值
  * @note   None
  * @param  id:软件定时器任务ID
  * @param  curTicks:设置的当前计数值
  * @retval None
  */
void timerA_setCurTicks(unsigned char id, unsigned int curTicks)
{
	timerATasks[id - 1].curTicks = curTicks;
}
/**
  * @brief  获取指定软件定时器任务的当前计数值
  * @note   None
  * @param  id:软件定时器任务ID
  * @retval 返回当前计数值
  */
unsigned int timerA_getCurTicks(unsigned char id)
{
	return timerATasks[id - 1].curTicks;
}
/**
  * @brief  设置指定软件定时器任务的目标计数值
  * @note   None
  * @param  id:软件定时器任务ID
  * @param  targetTicks:设置的目标计数值
  * @retval None
  */
void timerA_setTargetTicks(unsigned char id, unsigned int targetTicks)
{
	timerATasks[id - 1].targetTicks = targetTicks;
}
/**
  * @brief  获取指定软件定时器任务的目标计数值
  * @note   None
  * @param  id:软件定时器任务ID
  * @retval 返回目标计数值
  */
unsigned int timerA_getTargetTicks(unsigned char id)
{
	return timerATasks[id - 1].targetTicks;
}
/**
  * @brief  设置指定软件定时器任务ID的运行状态
  * @note   None
  * @param  id:软件定时器任务ID
  * @param  run:设置的运行状态
  * @retval None
  */
void timerA_setRun(unsigned char id, unsigned char run)
{
	timerATasks[id - 1].run = run;
}
/**
  * @brief  获取指定软件定时器任务的运行状态
  * @note   None
  * @param  id:软件定时器任务ID
  * @retval 返回运行状态
  */
unsigned char timerA_getRun(unsigned char id)
{
	return timerATasks[id - 1].run;
}
